﻿
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Collections;





namespace IntelligentCMS
{
    class CMSTagParser
    {

        static String str_CMSTagRegex = "(?:(?:\\s*>)|(?:\\s+(?:[A-Za-z0-9]+\\s*=\\s*\"[A-Za-z0-9]+\"\\s*)*\\s*>))"; //The rest of a tag. See the constructor.

        static String str_KeyValuePairRegex = "[^=\\s]+\\s*=\\s*\"[A-Za-z0-9]+\"";

        static String str_KeyRegex = "([^=\\s]+(?=\\s*=\\s*))"; //The key in a key/value pair.

        static String str_ValueRegex = "(?<=\")\\w+(?=\")"; //The value in a key/value pair.

        //On slurped text, if there is also a left bracket, accept at zero-width.
        static String str_TagRegex = "((?<=<\\s*)[A-Za-z0-9]+)";

        static Regex KeyValuePairRegex = new Regex(str_KeyValuePairRegex);
        static Regex KeyRegex = new Regex(str_KeyRegex);
        static Regex ValueRegex = new Regex(str_ValueRegex);
        static Regex TagRegex = new Regex(str_TagRegex);

        Regex CMSTagParserRegex;

        /*
         *Takes list of prefixes, creates extremely large OR junction out of them,
         *tacks it onto the beginning of the CMSTagRegex.
         */
        public CMSTagParser(List<String> prefixes)
        {
            string s = string.Empty;
            for (int i = 0; i < prefixes.Count; i++)
            {
                s += prefixes[i];
                if (i < prefixes.Count - 1)
                {
                    s += "|";
                }
            }
            //Huge unslurped OR junction, then the criterion for a bunch of key/value pairs.
            string finalregex = "<(?:" + s + ")" + str_CMSTagRegex;
            CMSTagParserRegex = new Regex(finalregex, RegexOptions.IgnoreCase);
        }

        //Given file as string, return mixed list of Strings and
        //CMSTags.
        public List<CMSTag> ParseTags(String s)
        {
            string buffer = s.Substring(0, s.Length);
            List<CMSTag> returnList = new List<CMSTag>();

            while (buffer.Length > 0 && CMSTagParserRegex.IsMatch(buffer))
            {
                Match match = CMSTagParserRegex.Match(buffer);
                string[] splitpoint = CMSTagParserRegex.Split(buffer, 2);
                if (splitpoint[0].Length != 0)
                {
                    returnList.Add(new CMSTag(splitpoint[0], null, null, true));
                }
                returnList.Add(ParseObject(match.Value));

                buffer = splitpoint[1];

            }
            // ROFL. Never a dull moment with this project.
            if (buffer.Length > 0)
            {
                returnList.Add(new CMSTag(buffer, null, null, true));

            }


            return returnList;
        }

        //Split individual tag into leading tag, and then into key/value pairs.
        public CMSTag ParseObject(String s)
        {
            MatchCollection keyvalue = KeyValuePairRegex.Matches(s);
            ArrayList keys = new ArrayList();
            ArrayList values = new ArrayList();
            String tag = TagRegex.Match(s).Value;

            foreach (Match keypair in keyvalue)
            {
                keys.Add(KeyRegex.Match(keypair.Value).Value);
                values.Add(ValueRegex.Match(keypair.Value).Value);
            }

            return new CMSTag(tag, keys, values, false);
        }

    }

}